package java_thinking.unit_21._21_5;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Semaphore;

/**
 * @Desc:   5-14 使用 Semaphore 为容器设置边界
 * @author: cww
 * @DateTime: 2019/6/6 19:19
 */

public class BoundedHashSet<T> {
    private final Set<T> set;
    private final Semaphore sem;

    /**
     * 信号量 的计数值初始化为容量的最大值
     * 底层的set实现并不知道关于边界的任何信息，这都是由 BoundeHashSet 来实现的
     * @param bound
     */
    public BoundedHashSet(int bound) {
        this.set = Collections.synchronizedSet(new HashSet<>());
        sem = new Semaphore(bound);
    }

    /**
     * 在向底层添加一个元素之前，要先获取一个许可，如果add操作没有添加任何元素
     * 那么会立刻释放许可
     * @param o
     * @return
     * @throws InterruptedException
     */
    public boolean add(T o) throws InterruptedException {
        sem.acquire();
        boolean wasAdded = false;
        try {
            wasAdded = set.add(o);
            return wasAdded;
        } finally {
            if (!wasAdded) {
                sem.release();
            }
        }
    }

    /**
     * remove 操作释放一个许可，使更多的元素能够添加到容器中
     * @param o
     * @return
     */
    public boolean remove(Object o) {
        boolean wasRemoved = set.remove(o);
        if (wasRemoved) {
            sem.release();
        }
        return wasRemoved;
    }
}
